1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.base;
18
19 import com.google.common.testing.GcFinalization;
20
21 import junit.framework.TestCase;
22
23 import java.io.Closeable;
24 import java.lang.ref.WeakReference;
25 import java.lang.reflect.Constructor;
26 import java.lang.reflect.Field;
27 import java.net.URL;
28 import java.net.URLClassLoader;
29 import java.security.Permission;
30 import java.security.Policy;
31 import java.security.ProtectionDomain;
32 import java.util.concurrent.Callable;
33 import java.util.concurrent.Semaphore;
34 import java.util.concurrent.TimeUnit;
35 import java.util.concurrent.atomic.AtomicReference;
36
37
38
39
40
41
42
43
44 public class FinalizableReferenceQueueClassLoaderUnloadingTest extends TestCase {
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 public static class MyFinalizableWeakReference extends FinalizableWeakReference<Object> {
64 public MyFinalizableWeakReference(Object x, FinalizableReferenceQueue queue) {
65 super(x, queue);
66 }
67
68 @Override
69 public void finalizeReferent() {
70 }
71 }
72
73 private static class PermissivePolicy extends Policy {
74 @Override
75 public boolean implies(ProtectionDomain pd, Permission perm) {
76 return true;
77 }
78 }
79
80 private WeakReference<ClassLoader> useFrqInSeparateLoader() throws Exception {
81 final URLClassLoader myLoader = (URLClassLoader) getClass().getClassLoader();
82 final URL[] urls = myLoader.getURLs();
83 URLClassLoader sepLoader = new URLClassLoader(urls, myLoader.getParent());
84
85
86
87
88
89
90 Class<?> frqC = FinalizableReferenceQueue.class;
91 Class<?> sepFrqC = sepLoader.loadClass(frqC.getName());
92 assertNotSame(frqC, sepFrqC);
93
94
95
96
97
98
99
100
101 Class<?> sepFrqSystemLoaderC =
102 sepLoader.loadClass(FinalizableReferenceQueue.SystemLoader.class.getName());
103 Field disabled = sepFrqSystemLoaderC.getDeclaredField("disabled");
104 disabled.setAccessible(true);
105 disabled.set(null, true);
106
107
108
109 AtomicReference<Object> sepFrqA = new AtomicReference<Object>(sepFrqC.newInstance());
110 Class<?> sepFwrC = sepLoader.loadClass(MyFinalizableWeakReference.class.getName());
111 Constructor<?> sepFwrCons = sepFwrC.getConstructor(Object.class, sepFrqC);
112
113 Class<?> sepStopwatchC = sepLoader.loadClass(Stopwatch.class.getName());
114 assertSame(sepLoader, sepStopwatchC.getClassLoader());
115 AtomicReference<Object> sepStopwatchA =
116 new AtomicReference<Object>(sepStopwatchC.getMethod("createUnstarted").invoke(null));
117 AtomicReference<WeakReference<?>> sepStopwatchRef = new AtomicReference<WeakReference<?>>(
118 (WeakReference<?>) sepFwrCons.newInstance(sepStopwatchA.get(), sepFrqA.get()));
119 assertNotNull(sepStopwatchA.get());
120
121 sepStopwatchA.set(null);
122 GcFinalization.awaitClear(sepStopwatchRef.get());
123
124
125 return new WeakReference<ClassLoader>(sepLoader);
126 }
127
128 private void doTestUnloadable() throws Exception {
129 WeakReference<ClassLoader> loaderRef = useFrqInSeparateLoader();
130 GcFinalization.awaitClear(loaderRef);
131 }
132
133 public void testUnloadableWithoutSecurityManager() throws Exception {
134
135
136 SecurityManager oldSecurityManager = System.getSecurityManager();
137 try {
138 System.setSecurityManager(null);
139 doTestUnloadable();
140 } finally {
141 System.setSecurityManager(oldSecurityManager);
142 }
143 }
144
145 public void testUnloadableWithSecurityManager() throws Exception {
146
147
148
149
150
151 Policy oldPolicy = Policy.getPolicy();
152 SecurityManager oldSecurityManager = System.getSecurityManager();
153 try {
154 Policy.setPolicy(new PermissivePolicy());
155 System.setSecurityManager(new SecurityManager());
156 doTestUnloadable();
157 } finally {
158 System.setSecurityManager(oldSecurityManager);
159 Policy.setPolicy(oldPolicy);
160 }
161 }
162
163 public static class FrqUser implements Callable<WeakReference<Object>> {
164 public static FinalizableReferenceQueue frq = new FinalizableReferenceQueue();
165 public static final Semaphore finalized = new Semaphore(0);
166
167 @Override
168 public WeakReference<Object> call() {
169 WeakReference<Object> wr = new FinalizableWeakReference<Object>(new Integer(23), frq) {
170 @Override
171 public void finalizeReferent() {
172 finalized.release();
173 }
174 };
175 return wr;
176 }
177 }
178
179 public void testUnloadableInStaticFieldIfClosed() throws Exception {
180 Policy oldPolicy = Policy.getPolicy();
181 SecurityManager oldSecurityManager = System.getSecurityManager();
182 try {
183 Policy.setPolicy(new PermissivePolicy());
184 System.setSecurityManager(new SecurityManager());
185 WeakReference<ClassLoader> loaderRef = doTestUnloadableInStaticFieldIfClosed();
186 GcFinalization.awaitClear(loaderRef);
187 } finally {
188 System.setSecurityManager(oldSecurityManager);
189 Policy.setPolicy(oldPolicy);
190 }
191 }
192
193
194
195
196
197
198
199
200
201
202
203
204 private WeakReference<ClassLoader> doTestUnloadableInStaticFieldIfClosed() throws Exception {
205 final URLClassLoader myLoader = (URLClassLoader) getClass().getClassLoader();
206 final URL[] urls = myLoader.getURLs();
207 URLClassLoader sepLoader = new URLClassLoader(urls, myLoader.getParent());
208
209 Class<?> frqC = FinalizableReferenceQueue.class;
210 Class<?> sepFrqC = sepLoader.loadClass(frqC.getName());
211 assertNotSame(frqC, sepFrqC);
212
213 Class<?> sepFrqSystemLoaderC =
214 sepLoader.loadClass(FinalizableReferenceQueue.SystemLoader.class.getName());
215 Field disabled = sepFrqSystemLoaderC.getDeclaredField("disabled");
216 disabled.setAccessible(true);
217 disabled.set(null, true);
218
219 Class<?> frqUserC = FrqUser.class;
220 Class<?> sepFrqUserC = sepLoader.loadClass(frqUserC.getName());
221 assertNotSame(frqUserC, sepFrqUserC);
222 assertSame(sepLoader, sepFrqUserC.getClassLoader());
223
224 Callable<?> sepFrqUser = (Callable<?>) sepFrqUserC.newInstance();
225 WeakReference<?> finalizableWeakReference = (WeakReference<?>) sepFrqUser.call();
226
227 GcFinalization.awaitClear(finalizableWeakReference);
228
229 Field sepFrqUserFinalizedF = sepFrqUserC.getField("finalized");
230 Semaphore finalizeCount = (Semaphore) sepFrqUserFinalizedF.get(null);
231 boolean finalized = finalizeCount.tryAcquire(5, TimeUnit.SECONDS);
232 assertTrue(finalized);
233
234 Field sepFrqUserFrqF = sepFrqUserC.getField("frq");
235 Closeable frq = (Closeable) sepFrqUserFrqF.get(null);
236 frq.close();
237
238 return new WeakReference<ClassLoader>(sepLoader);
239 }
240 }